﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Windows.Threading;

namespace PTExpress.Templates
{
    /// <summary>
    /// Interaction logic for SpinningProgress.xaml
    /// </summary>
    public partial class ucSpinningProgress : UserControl
    {
        #region Data

        private Color m_InactiveColour = Color.FromRgb(218, 218, 218);
        private Color m_ActiveColour = Color.FromRgb(35, 146, 33);
        private Color m_TransistionColour = Color.FromRgb(129, 242, 121);
        
        private Path[] segments = new Path[12];

        private bool m_AutoIncrement = true;
        private double m_IncrementFrequency = 100;
        private bool m_BehindIsActive = true;
        private int m_TransitionSegment = 0;

        private DispatcherTimer m_AutoRotateTimer;

        #endregion // Data ----------------------------------------------------------------------------------------

        #region Properties

        [DefaultValue(typeof(Color), "218, 218, 218")]
        public Color InactiveSegmentColour
        {
            get
            {
                return m_InactiveColour;
            }
            set
            {
                m_InactiveColour = value;
                Invalidate();
            }
        }

        [DefaultValue(typeof(Color), "35, 146, 33")]
        public Color ActiveSegmentColour
        {
            get
            {
                return m_ActiveColour;
            }
            set
            {
                m_ActiveColour = value;
                Invalidate();
            }
        }

        [DefaultValue(typeof(Color), "129, 242, 121")]
        public Color TransistionSegmentColour
        {
            get
            {
                return m_TransistionColour;
            }
            set
            {
                m_TransistionColour = value;
                Invalidate();
            }
        }

        [DefaultValue(true)]
        public bool BehindTransistionSegmentIsActive
        {
            get
            {
                return m_BehindIsActive;
            }
            set
            {
                m_BehindIsActive = value;
                Invalidate();
            }
        }

        [DefaultValue(-1)]
        public int TransistionSegment
        {
            get
            {
                return m_TransitionSegment;
            }
            set
            {
                if (value > 11 || value < -1)
                {
                    throw new ArgumentException("TransistionSegment must be between -1 and 11");
                }
                m_TransitionSegment = value;
                Invalidate();
            }
        }

        [DefaultValue(true)]
        public bool AutoIncrement
        {
            get
            {
                return m_AutoIncrement;
            }
            set
            {
                m_AutoIncrement = value;

                if (value == false)
                {
                    m_AutoRotateTimer.Stop();
                }else
                {
                    m_AutoRotateTimer.Start();
                }
            }
        }

        [DefaultValue(100)]
        public double AutoIncrementFrequency
        {
            get
            {
                return m_IncrementFrequency;
            }
            set
            {
                m_IncrementFrequency = value;
                m_AutoRotateTimer.Interval = TimeSpan.FromMilliseconds(m_IncrementFrequency);
            }
        }

        #endregion // Properties ----------------------------------------------------------------------------------

        public ucSpinningProgress()
        {
            InitializeComponent();
            m_AutoRotateTimer = new DispatcherTimer();
            m_AutoRotateTimer.Interval = TimeSpan.FromMilliseconds(m_IncrementFrequency);
            m_AutoRotateTimer.Tick += new EventHandler(IncrementTransisionSegment);
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            CalculateSegments();
            
            m_AutoRotateTimer.Start();

            this.SizeChanged += new SizeChangedEventHandler(ProgressDisk_SizeChanged);
        }

        private void IncrementTransisionSegment(object sender, EventArgs e)
        {
            if (m_TransitionSegment == 11)
            {
                m_TransitionSegment = 0;
                m_BehindIsActive = !(m_BehindIsActive);
            }
            else if (m_TransitionSegment == -1)
            {
                m_TransitionSegment = 0;
            }
            else
            {
                m_TransitionSegment += 1;
            }
            Invalidate();
        }

        private void CalculateSegments()
        {
            canvas.Children.Clear();

            Double width = canvas.ActualWidth / 2;
            Double height = canvas.ActualHeight / 2;

            for (int intCount = 0; intCount < 12; intCount++)
            {
                int angle = (intCount * 30) - 90;

                segments[intCount] = CreatePie(width, height, angle);
                Canvas.SetLeft(segments[intCount], width);
                Canvas.SetTop(segments[intCount], height);
                canvas.Children.Add(segments[intCount]);
            }

            Ellipse elInner = new Ellipse
            {
                Width = (canvas.ActualWidth - ((canvas.ActualWidth * 14) / 30)),
                Height = (canvas.ActualHeight - ((canvas.ActualHeight * 14) / 30)),
                Fill = this.Background
            };
            canvas.Background = Brushes.Transparent;
            Canvas.SetTop(elInner, height - elInner.Height / 2);
            Canvas.SetLeft(elInner, width - elInner.Width / 2);
            canvas.Children.Add(elInner);
        }

        private void ProgressDisk_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            CalculateSegments();
        }

        private Path CreatePie(double width, double height, int angle)
        {
            Path path = new Path();
            path.Fill = new SolidColorBrush(m_InactiveColour);

            PathGeometry pathGeometry = new PathGeometry();
            PathFigure pathFigure = new PathFigure();
            pathFigure.StartPoint = new Point(0, 0);

            LineSegment lineSegment = new LineSegment(new Point(width * Math.Cos(angle * Math.PI / 180),
                                                            height * Math.Sin(angle * Math.PI / 180)), true);
            pathFigure.Segments.Add(lineSegment);

            angle += 25;
            ArcSegment arcSegment = new ArcSegment();
            arcSegment.Point = new Point(width * Math.Cos(angle * Math.PI / 180),
                                        height * Math.Sin(angle * Math.PI / 180));
            arcSegment.Size = new Size(width, height);
            arcSegment.SweepDirection = SweepDirection.Clockwise;
            pathFigure.Segments.Add(arcSegment);

            pathGeometry.Figures.Add(pathFigure);
            path.Data = pathGeometry;
            return path;
        }

        private void Invalidate()
        {
            if (segments[0] == null)
                return;
            for (int intCount = 0; intCount < 12; intCount++)
            {
                if (intCount == m_TransitionSegment)
                {
                    // If this segment is the transistion segment, colour it differently
                    segments[intCount].Fill = new SolidColorBrush(m_TransistionColour);
                }
                else if (intCount < m_TransitionSegment)
                {
                    // This segment is behind the transistion segment
                    if (m_BehindIsActive)
                    {
                        // If behind the transistion should be active, 
                        // colour it with the active colour
                        segments[intCount].Fill = new SolidColorBrush(m_ActiveColour);
                    }
                    else
                    {
                        // If behind the transistion should be in-active, 
                        // colour it with the in-active colour
                        segments[intCount].Fill = new SolidColorBrush(m_InactiveColour);
                    }
                }
                else
                {
                    // This segment is ahead of the transistion segment
                    if (m_BehindIsActive)
                    {
                        // If behind the the transistion should be active, 
                        // colour it with the in-active colour
                        segments[intCount].Fill = new SolidColorBrush(m_InactiveColour);
                    }
                    else
                    {
                        // If behind the the transistion should be in-active, 
                        // colour it with the active colour
                        segments[intCount].Fill = new SolidColorBrush(m_ActiveColour);
                    }
                }
               
            } 
        }
    }
}
